The ONE所支持的移动模型movement,实际是以某种规则产生一系列连接建立或撤消的事件。本文介绍连接事件的读取和事件处理。连接事件在初始化时预读取500个,待到处理完后再读取500个,如此反复。
1. 概述
The ONE所支持的移动模型movement,实际是以某种规则产生一系列连接建立或撤消的事件,其形式如下:
21574 CONN 1 40 up
21687 CONN 1 40 down
这些事件被加入到事件队列(List<EventQueue> queues
),供EventQueueHandler
处理,详情可参考博文《宏观角度理解事件是如何组织》。
The ONE所支持的移动模型可以理解成先生成上述格式的文本文件(每一行对应着一个事件),而后The ONE从该文件读取事件。在设置文件my_settings.txt
中设置连接事件文件的路径,举例如下:
Events1.class = ExternalEventsQueue
Events1.filePath = nc/traces_pan/one_infocom06.dat
ConnectionEvent
类用来描述一个连接事件,包含如下成员变量(跟Connection
类差不多):
protected double time; //ExternalEvent.java 事件触发时间(单位:秒)
//ConnectionEvent.java
protected String interfaceId; //the interfaceId number for this event
protected int fromAddr;
protected int toAddr;
protected boolean isUp; //true为连接建立up,false为连接撤消down
2. 读取事件
2.1 初始化读取
The ONE初始化会创建场景SimScenario()
,SimScenario()
会创建事件队列处理EventQueueHandle
实例(用于处理The ONE所有事件),EventQueueHandle构造函数包含如下语句,用于读取500个连接事件,并加入到queues
。
queues.add(new ExternalEventsQueue(path, preload)); //创建外部事件,并加入到queues
preload
是预读取的事件数,可以通过settings文件,修改默认值,如下:
public static final int DEFAULT_NROF_PRELOAD = 500 //ExternalEventsQueue.java
Events1.class = ExternalEventsQueue
Events1.nrofPreload = …
ExternalEventsQueue
构造函数展开,关键源代码如下:
//ExternalEventsQueue.java
public ExternalEventsQueue(String filePath, int nrofPreload) {
setNrofPreload(nrofPreload);
init(filePath);
}
//init(filePath); private void init(String eeFilePath)
this.reader = new StandardEventsReader(eventsFile); //StandardEventsReader,实为new BufferedReader(new FileReader(filePath)),为读取文件做准备
this.queue = readEvents(nrofPreload);
//this.queue = readEvents(nrofPreload);
List<ExternalEvent> events = reader.readEvents(nrof);
2.2 后续读取
当初始化读取的500个事件处理完后,再读取500个,如此反复读取。在DTNSim.main –> new DTNSimTextUI().start –> DTNSimTextUI.runSim –> World.update
包含如下语句:
//World.java中update()
ExternalEvent ee = this.nextEventQueue.nextEvent();
ee.processEvent(this);
ExternalEventsQueue.java
中的nextEvent()
,当连接事件处理完后,再读取500个事件,源代码如下:
//ExternalEventsQueue.java中的nextEvent()
public ExternalEvent nextEvent() {
if (queue.size() == 0) { // no more events
return new ExternalEvent(Double.MAX_VALUE);
}
ExternalEvent ee = queue.get(nextEventIndex);
nextEventIndex++;
if (nextEventIndex >= queue.size()) { //ran out of events
queue = readEvents(nrofPreload); //再次读取事件
nextEventIndex = 0;
}
return ee;
}
3. 事件处理
处理连接事件很简单,即将连接(实际操作的是网络接口,Interface
)标识为建立或撤消,相关源代码如下:
//ConnectionEvent.java
public void processEvent(World world) {
DTNHost from = world.getNodeByAddress(this.fromAddr);
DTNHost to = world.getNodeByAddress(this.toAddr);
from.forceConnection(to, interfaceId, this.isUp); //建立连接
}
//DTNHost.java中的forceConnection(DTNHost anotherHost, String interfaceId, boolean up)
if (up) {
ni.createConnection(no);
} else {
ni.destroyConnection(no);
}